home *** CD-ROM | disk | FTP | other *** search
/ The Best of Mecomp Multimedia 1 / Mecomp-CD.iso / amiga / player / ahi / developer / docs / programming guidelines.ascii < prev    next >
Encoding:
Text File  |  1996-06-04  |  10.9 KB  |  248 lines

  1.  
  2. How Things Are Supposed To Be Done
  3. ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
  4.  
  5.  This is just a quick guide to help you write Software That Works (TM).
  6. This document is only a draft at the moment, so please report errors and
  7. improvements to me (lcs@lysator.liu.se). Please use common sence while reading
  8. it, there are probably errors.
  9.  
  10.  
  11.  
  12.  
  13. 1. Opening and closing 'ahi.device' for low-level access.
  14.  
  15.    Not too hard. Just open 'ahi.device' unit 'AHI_NO_UNIT'. After that
  16.   you can access all the functions of the device just as if you had
  17.   opened a standard shared library.
  18.  
  19.    For the assembler programmer I have written two macros; OPENAHI and
  20.   CLOSEAHI. Here is a small example:
  21.  
  22.           OPENAHI 2   ;Open at least version 2 of 'ahi.device'.
  23.           lea     _AHIBase(pc),a0
  24.           move.l  d0,(a0)
  25.           beq     error
  26.  
  27.   ; AHIs functions can now be called as normal library functions:
  28.           move.l  _AHIBase(pc),a6
  29.           moveq   #AHI_INVALID_ID,d0
  30.           jsr     _LVOAHI_NextAudioID
  31.  
  32.   error:
  33.           CLOSEAHI
  34.           rts
  35.  
  36.    Note that you HAVE to execute the CLOSEAHI macro even if OPENAHI failed!
  37.  
  38.  
  39.    For the C programmer, here is how it should be done:
  40.  
  41.   struct Library    *AHIBase;
  42.   struct MsgPort    *AHImp=NULL;
  43.   struct AHIRequest *AHIio=NULL;
  44.   BYTE               AHIDevice=-1;
  45.  
  46.   if(AHImp=CreateMsgPort())
  47.   {
  48.     if(AHIio=(struct AHIRequest *)CreateIORequest(AHImp,sizeof(struct AHIRequest)))
  49.     {
  50.       AHIio->ahir_Version=2;  // Open at least version 2 of 'ahi.device'.
  51.       if(!(AHIDevice=OpenDevice(AHINAME,AHI_NO_UNIT,(struct IORequest *)AHIio,NULL)))
  52.       {
  53.         AHIBase=(struct Library *)AHIio->ahir_Std.io_Device;
  54.  
  55.   // AHIs functions can now be called as normal library functions:
  56.         AHI_NextAudioID(AHI_INVALID_ID);
  57.  
  58.         CloseDevice((struct IORequest *)AHIio);
  59.         AHIDevice=-1; // Good habit, IMHO.
  60.       }
  61.       DeleteIORequest((struct IORequest *)AHIio);
  62.       AHIio=NULL;
  63.     }
  64.     DeleteMsgPort(AHImp);
  65.     AHImp=NULL;
  66.   }
  67.  
  68.  
  69.  
  70.  
  71. 2.1 Getting and releasing control of the hardware.
  72.  
  73.    If you wish to call other functions than 
  74.     AHI_AllocAudioRequestA()
  75.     AHI_AudioRequestA()
  76.     AHI_BestAudioIDA()
  77.     AHI_FreeAudioRequest()
  78.     AHI_GetAudioAttrsA()
  79.     AHI_NextAudioID()
  80.   you have to allocate the actual sound hardware. This is done with
  81.   AHI_AllocAudioA(). AHI_AllocAudioA() returns an AHIAudioCtrl structure,
  82.   or NULL if the hareware could not be allocated. The AHIAudioCtrl
  83.   structure has only one public field, ahiac_UserData. This is for
  84.   you use, you may read and write it at will.
  85.    If AHI_AllocAudioA() fails, it is important that you handle the
  86.   situation  gracefully.
  87.  
  88.    When you have finished playing or recording audio, call AHI_FreeAudio() to
  89.   deallocate the hardware and other resources allocated by AHI_AllocAudioA().
  90.  
  91.  
  92. 2.2 AHI_AllocAudioA() tags.
  93.  
  94.   AHI_AllocAudioA() takes several tags as input.
  95.  
  96.     AHIA_AudioID: This is the audio mode to be used. You must not use
  97.       any hardcoded values other than AHI_DEFAULT_ID, which is the user's
  98.       default fallback ID. AHI_AllocAudioA() is the only function that will
  99.       accepts AHI_DEFAULT_ID, so don't try to use it with others. In most
  100.       cases you should ask the user for an ID code (with AHI_AudioRequestA())
  101.       and then store the value in your settings file.
  102.     AHIA_MixFreq: This is the mixing frequency to be used. The actual
  103.       frequency will be rounded to the nearest frequency supported by the
  104.       sound hardware. To find the actual frequency, use AHI_GetAudioAttrsA().
  105.       If omitted or AHI_DEFAULT_FREQ, the user's preferred fallback
  106.       frequency will be used. In most cases you should ask the user for an ID
  107.       code (with AHI_AudioRequestA()) and then store the value in your
  108.       settings file.
  109.     AHIA_Channels: All sounds are played on a channel, this tag selects how
  110.       many you wish to use. In general it takes more CPU power the more
  111.       channels you use, and the volume gets lower and lower.
  112.     AHIA_Sounds: You must tell AHI how many different samples/sounds you
  113.       are going to play. See section 3 for more information.
  114.     AHIA_SoundFunc: With this tag you tell AHI to call a Hook when a sound
  115.       has been started.  It works just like Paulas audio interrupts. The
  116.       Hook recieves a AHISoundMessage structure as message. 
  117.       AHISoundMessage->ahism_Channel indicates which channel the sound that
  118.       caused the Hook to be called is played on.
  119.     AHIA_PlayerFunc: If you are going to play a musical score, you should
  120.       use this "interupt" source instead of VBLANK or CIA timers in order
  121.       to get the best result for all audio drivers. If you cannot use this,
  122.       you must not use any 'non-realtime' modes (see AHI_GetAudioAttrsA()
  123.       in the autodocs (the AHIDB_Realtime tag)).
  124.     AHIA_PlayerFreq: If non-zero, enables timing and specifies how many times
  125.       per second PlayerFunc will be called.  This must be specified if
  126.       AHIA_PlayerFunc is! It is suggested that you keep the frequency below
  127.       100-200 Hz.
  128.     AHIA_MinPlayerFreq: The minimum frequency (AHIA_PlayerFreq) you will
  129.       use. You should always supply this if you are using the device's
  130.       interrupt feature!
  131.     AHIA_MaxPlayerFreq: The maximum frequency (AHIA_PlayerFreq) you will
  132.       use. You should always supply this if you are using the device's
  133.       interrupt feature!
  134.     AHIA_RecordFunc: This hook will be called regulary when sampling is
  135.       turned on (see AHI_ControlAudioA()). It is important that you always
  136.       check the format of the sampled data, and ignore it if you can't
  137.       parse it. Since this hook may be called from an interrupt, it is not
  138.       legal to directly Write() the buffer to disk. To record directly to
  139.       harddisk you'll have to copy the samples to another buffer and signal
  140.       a process to save it. To find out the needed size of the buffer, see
  141.       AHI_GetAudioAttrsA() in the autodocs (the AHIDB_MaxRecordSamples tag).
  142.     AHIA_UserData: Can be used to initialise the ahiac_UserData field.
  143.       You do not have to use this tag to change ahiac_UserData, you may
  144.       write to it directly.
  145.  
  146.  
  147.  
  148.  
  149. 3. Loading and unloading sounds.
  150.  
  151.    Before you can play a sample array, you must AHI_LoadSound() it. Why? Because
  152.   if AHI knows what kind of sounds that will be played later, tables and
  153.   stuff can be set up in advance. Some drivers may even upload the samples
  154.   to the sound cards local RAM and play all samples from there, drastically
  155.   reducing CPU and bus load.
  156.    AHI_LoadSound() also associates each sound or sample with a number,
  157.   which is later used to refer to that particular sound.
  158.    There are 3 type of sounds, namely AHIST_SAMPLE, AHIST_DYNAMICSAMPLE and
  159.   AHIST_INPUT.
  160.     AHIST_SAMPLE: This is used for static samples. Most sounds that will be
  161.       played are of this type. Once the sample has been 'loaded', you may
  162.       not alter the memory where the sample is located.
  163.     AHIST_DYNAMICSAMPLE: If you wish to play a sample that you calculate in
  164.       realtime, or load in portions from disk, you must use this type.
  165.       These samples will never be uploaded to a sound cards local RAM, but
  166.       always played from the normal memory. There is a catch, however.
  167.       Because of the fact that the sound is mixed in chunks, you must have
  168.       a certain number of samples in memory before you start a sound of
  169.       this type. To calculate the size of the buffer (in samples), use the
  170.       following formula:
  171.         size = samples * Fs / Fm
  172.       where samples is the value retured from AHI_GetAudioAttrsA() when
  173.       called with the AHIDB_MaxPlaySamples tag, Fs is the highest frequency
  174.       the sound will be played at and Fm is the actual mixing frequency
  175.       (AHI_ControlAudioA()/AHIC_MixFreq_Query).
  176.      AHIST_INPUT: This sound type is used if you want to hear what you are
  177.       sampling. [It does not work yet.]
  178.  
  179.    If you know that you wont use a sound anymore, call AHI_UnloadSound().
  180.   AHI_FreeAudio() will also do that for you for any sounds left when called.
  181.  
  182.  
  183.  
  184.  
  185. 4. Playing a sound.
  186.  
  187.    After you have allocated the sound hardware and declared all your
  188.   samples, we're ready to start playback. This is done with a call to
  189.   AHI_ControlAudioA(), with the AHIC_Play tag set to TRUE. When this
  190.   function returns the PlayerFunc (See AHI_AllocAudioA()) is active, and
  191.   the audio driver is feeding zeros to the sound hardware. All you have
  192.   to do now is to set the desired sound, it's frequency and volume. This is
  193.   done with AHI_SetSound(), SetFreq() and SetVol(). Make sure the AHISB_IMM
  194.   bit is set for all these functions flag argument. And don't try to modify
  195.   a channel that is out of range. If you have allocated 4 channels you may
  196.   only modify channels 0-3.
  197.    The sound will not start until both AHI_SetSound() and SetFreq() has
  198.   been called. The sound will play even if SetVol() was not called, but it
  199.   will play completely silent.
  200.    When the sound has been started it will play till the end and then
  201.   repeat again. In order to play a one-shot sample you'll have to install a
  202.   sample interrupt, using the AHIA_SoundFunc tag with AHI_AllocAudioA().
  203.   For more information about using sample interrupt, see section 5.
  204.  
  205.    A little note regarding AHI_SetSound(). Offset is the first sample that
  206.   will be played, both when playing backwards and forwards. This means that
  207.   if you call AHI_SetSound() with offset 0 and lengh 4, sample 0,1,2 and 3
  208.   will be played. If you call AHI_SetSound() with offset 3 and length -4,
  209.   sample 3,2,1 and 0 will be played.
  210.  
  211.  
  212.  
  213.  
  214. 5. Using sample interrupts.
  215.  
  216.    Earlier versions of AHI had support for loops in sounds, but this support
  217.   has been dropped as of this version (temporary?). To play a one-shot
  218.   sample or an instrument where the one-shot part and the repeat part is
  219.   not equal, a sample interrupt needs to be used. AHIs SoundFunc works like
  220.   Paulas interrupts and is very easy to use.
  221.    The SoundFunc Hook will be called with an AHIAudioCtrl structure as
  222.   object and an AHISoundMessage structure as message. ahism_Channel
  223.   indicates which channel caused the hook to be called.
  224.    An example SoundFunc which handles the repeat part of an instrument can
  225.   look like this:
  226.  
  227.   __asm __saveds ULONG SoundFunc(register __a0 struct Hook *hook,
  228.       register __a2 struct AHIAudioCtrl *actrl,
  229.       register __a1 struct AHISoundMessage *chan)
  230.   {
  231.     if(ChannelDatas[chan->ahism_Channel].Length)
  232.       AHI_SetSound(chan->ahism_Channel,0,
  233.           (ULONG) ChannelDatas[chan->ahism_Channel].Address,
  234.           ChannelDatas[chan->ahism_Channel].Length,
  235.           actrl,NULL);
  236.     else
  237.       AHI_SetSound(chan->ahism_Channel,AHI_NOSOUND,NULL,NULL,actrl,NULL);
  238.     return NULL;
  239.   }
  240.  
  241.    This example is from the AHI NotePlayer for DeliTracker 2. ChannelDatas
  242.   is an array where the start and length of the repeat part is stored. A
  243.   repeat length of zero indicates a one-shot sound. Note that this
  244.   particular example only uses one sound (0). For applications using
  245.   multiple sounds, the sound number would have to be stored in the array as
  246.   well.
  247.    Note that the AHISF_IMM flag should NEVER be set in a SoundFunc Hook!
  248.